﻿namespace Autodesk.Revit.DB;

/// <summary>
/// Autodesk.Revit.DB.Transaction 的扩展方法
/// </summary>
public static class TransactionExtensions
{
    /// <summary>
    /// 忽略事务的警告通知
    /// </summary>
    /// <param name="transaction"></param>
    /// <param name="isUse">是否启用</param>
    public static Transaction IgnoreWarning(this Transaction transaction, bool isUse = true)
    {
        if (isUse)
        {
            return transaction.SetFailuresPreprocessor(fa =>
            {
                var fms = fa.GetFailureMessages();

                if (fms.Count == 0)
                {
                    return FailureProcessingResult.Continue;
                }

                foreach (var fm in fms)
                {
                    if (fm.GetSeverity() == FailureSeverity.Warning)
                    {
                        fa.DeleteWarning(fm);
                    }
                }
                return FailureProcessingResult.ProceedWithCommit;
            });
        }
        return transaction;
    }

    /// <summary>
    /// 处理事务的错误通知
    /// </summary>
    /// <returns></returns>
    public static Transaction ResolveFailure(this Transaction transaction, bool isUse = true)
    {
        if (isUse)
        {
            return transaction.SetFailuresPreprocessor(fa =>
            {
                var fms = fa.GetFailureMessages();

                if (fms.Count == 0)
                {
                    return FailureProcessingResult.Continue;
                }

                foreach (var fm in fms)
                {
                    if (fm.GetSeverity() == FailureSeverity.Error && fm.HasResolutions())
                        fa.ResolveFailure(fm);
                }
                return FailureProcessingResult.ProceedWithCommit;
            });
        }
        return transaction;
    }

    /// <summary>
    /// 处理任务通知
    /// </summary>
    /// <param name="transaction"></param>
    /// <param name="isIgnoreWarning"></param>
    /// <param name="isResolveFailure"></param>
    /// <returns></returns>
    public static Transaction HandlingOptions(this Transaction transaction, bool isIgnoreWarning, bool isResolveFailure)
    {
        if (isIgnoreWarning || isResolveFailure)
        {
            return transaction.SetFailuresPreprocessor(fa =>
            {
                var fms = fa.GetFailureMessages();

                if (fms.Count == 0)
                {
                    return FailureProcessingResult.Continue;
                }

                foreach (var fm in fms)
                {
                    if (isIgnoreWarning && fm.GetSeverity() == FailureSeverity.Warning)
                    {
                        fa.DeleteWarning(fm);
                    }

                    if (isResolveFailure && fm.GetSeverity() == FailureSeverity.Error && fm.HasResolutions())
                    {
                        fa.ResolveFailure(fm);
                    }
                }
                return FailureProcessingResult.ProceedWithCommit;
            });
        }

        return transaction;
    }

    /// <summary>
    /// 设置在故障处理开始时调用的回调函数。
    /// </summary>
    /// <param name="transaction"></param>
    /// <param name="failuresPreprocessor"></param>
    /// <returns></returns>
    public static Transaction SetFailuresPreprocessor(this Transaction transaction, IFailuresPreprocessor failuresPreprocessor)
    {
        FailureHandlingOptions fho = transaction
                .GetFailureHandlingOptions()
                .SetFailuresPreprocessor(failuresPreprocessor);
        transaction.SetFailureHandlingOptions(fho);
        return transaction;
    }

    /// <summary>
    /// 自定义设置在故障处理开始时调用的回调函数。
    /// </summary>
    /// <param name="transaction"></param>
    /// <param name="func"></param>
    /// <returns></returns>
    public static Transaction SetFailuresPreprocessor(this Transaction transaction, Func<FailuresAccessor, FailureProcessingResult> func)
    {
        return transaction.SetFailuresPreprocessor(new FailuresPreprocessorHandler(func));
    }

    /// <summary>
    /// 以一个指定的名称启动事务并设置是否忽略警告或错误消息
    /// </summary>
    /// <param name="transaction"></param>
    /// <param name="name"></param>
    /// <param name="isIgnoreWarning"></param>
    /// <param name="isResolveFailure"></param>
    /// <returns></returns>
    public static TransactionStatus Start(this Transaction transaction, string name, bool isIgnoreWarning = false, bool isResolveFailure = false)
    {
        TransactionStatus status = transaction.Start(name);
        transaction.HandlingOptions(isIgnoreWarning, isResolveFailure);
        return status;
    }

    /// <summary>
    /// 启动事务并设置是否忽略警告或错误消息
    /// </summary>
    /// <param name="transaction"></param>
    /// <param name="isIgnoreWarning"></param>
    /// <param name="isResolveFailure"></param>
    /// <returns></returns>
    public static TransactionStatus Start(this Transaction transaction, bool isIgnoreWarning = false, bool isResolveFailure = false)
    {
        TransactionStatus status = transaction.Start();
        transaction.HandlingOptions(isIgnoreWarning, isResolveFailure);
        return status;
    }
}
